记一次MySQL批量更新SQL优化,性能提升几十个数量级

您所在的位置:网站首页 sql foreach卡死 记一次MySQL批量更新SQL优化,性能提升几十个数量级

记一次MySQL批量更新SQL优化,性能提升几十个数量级

2024-07-18 04:44:35| 来源: 网络整理| 查看: 265

目录

一、问题背景

二、实现方案历程

2.1 方案1

2.2 方案2

2.3 方案3

一、问题背景

        原始需求是这样的,100个计数器硬件设备每隔5秒给服务器上报计数信息,服务端收到消息后先将上报的元数据存储起来,再每隔10s批量对之前上报的所有的元数据按时间段进行批量累加统计更新(题外话,为什么要每隔10s处理一次,而不是上报一次就累加一次?是为了不频繁操作数据库)

        经过优化之后,批量更新SQL从58109ms耗时下降到了124ms。

二、实现方案历程

        在看实现方案前,我们先看一下表的设计,其余的业务相关字段大家可以先忽略,主要就是要对相应时间段的finish_count做累加计算。当前表aps_produce_statistics中有73w条数据。

CREATE TABLE `aps_produce_statistics` (   `produce_id` bigint(20) NOT NULL COMMENT '生产任务id',   `line_id` bigint(20) NOT NULL COMMENT '产线id',   `shift` tinyint(2) NOT NULL COMMENT '班次 0-白班 1-夜班',   `time_segment` tinyint(2) NOT NULL COMMENT '所在时间段,1-10',   `plan_count` int(10) DEFAULT NULL COMMENT '时间段内的计划数',   `finish_count` int(10) NOT NULL COMMENT '完成量',   `plan_id` bigint(20) NOT NULL COMMENT '计划id',   `order_id` bigint(20) NOT NULL COMMENT '订单id',   `produce_time` date DEFAULT NULL COMMENT '生产时间' ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

        项目用的是springboot+mybatis框架。

2.1 方案1

        将多个update语句通过 连接起来,生成的SQL就是以;分割的多个update语句。这样的效率是最差的,每执行一个update就要进行全表扫描,如果循环200次,那么耗时就是58109ms。

update aps_produce_statistics set finish_count = finish_count + #{item.finishCount} WHERE produce_id = #{item.produceId} and time_segment = #{item.timeSegment} update aps_produce_statistics set finish_count = finish_count + 2 WHERE produce_id = 1 and time_segment = 1; update aps_produce_statistics set finish_count = finish_count + 3 WHERE produce_id = 1 and time_segment = 2; 2.2 方案2

        方案1每次都要进行全表扫描,且进行了200次循环,共扫描了200*73w=14600w的数据,速度是可想而知的,所以这次我们给表加上联合索引,联合索引的字段就是where后的两个条件子段produce_id + time_segment。加了索引之后的建表语句如下:

CREATE TABLE `aps_produce_statistics` (   `produce_id` bigint(20) NOT NULL COMMENT '生产任务id',   `line_id` bigint(20) NOT NULL COMMENT '产线id',   `shift` tinyint(2) NOT NULL COMMENT '班次 0-白班 1-夜班',   `time_segment` tinyint(2) NOT NULL COMMENT '所在时间段,1-10',   `plan_count` int(10) DEFAULT NULL COMMENT '时间段内的计划数',   `finish_count` int(10) NOT NULL COMMENT '完成量',   `plan_id` bigint(20) NOT NULL COMMENT '计划id',   `order_id` bigint(20) NOT NULL COMMENT '订单id',   `produce_time` date DEFAULT NULL COMMENT '生产时间',   KEY `proId_timeseg` (`produce_id`,`time_segment`) COMMENT '生产任务id加时间段的联合索引' ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

        SQL还是像方案1一样,这次耗时下降到了 4819ms。

2.3 方案3

        虽然加了索引之后,性能提升了不少,但还是需要将近5s,显然还是要继续优化的。思路就是先创建一张临时表,然后将要更新的数据批量插入到这张表里面,接着联合aps_produce_statistics和临时表进行批量update,只执行一次update指令,减少了扫描的行数。最终耗时下降到了124ms。

create temporary table statistics_tmp(produce_id bigint(20), time_segment tinyint(2), count int(10), KEY `proId_timeseg` (`produce_id`,`time_segment`)); insert into statistics_tmp values (#{item.produceId}, #{item.timeSegment}, #{item.finishCount}) update aps_produce_statistics st, statistics_tmp temp set st.finish_count=st.finish_count + temp.count where st.produce_id=temp.produce_id and st.time_segment = temp. time_segment;



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


    图片新闻

    实验室药品柜的特性有哪些
    实验室药品柜是实验室家具的重要组成部分之一,主要
    小学科学实验中有哪些教学
    计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
    实验室各种仪器原理动图讲
    1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
    高中化学常见仪器及实验装
    1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
    微生物操作主要设备和器具
    今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
    浅谈通风柜使用基本常识
     众所周知,通风柜功能中最主要的就是排气功能。在

    专题文章

      CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭